home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / crypt / idea.lha / orig_idea.c < prev    next >
C/C++ Source or Header  |  1992-05-12  |  33KB  |  980 lines

  1. /* #define rasterAndTime          uncomment this line if you use raster files */
  2.  
  3. /******************************************************************************/
  4. /*                                                                            */
  5. /* I N T E R N A T I O N A L  D A T A  E N C R Y P T I O N  A L G O R I T H M */
  6. /*                                                                            */
  7. /******************************************************************************/
  8. /* Author:       Richard De Moliner (demoliner@isi.ethz.ch)                   */
  9. /*               Signal and Information Processing Laboratory                 */
  10. /*               Swiss Federal Institute of Technology                        */
  11. /*               CH-8092 Zuerich, Switzerland                                 */
  12. /* Last Edition: 23 April 1992                                                */
  13. /* System:       SUN SPARCstation, SUN cc C-Compiler, SUN-OS 4.1.1            */
  14. /******************************************************************************\
  15. NAME
  16.      idea - encrypt and decrypt using IDEA
  17.  
  18. SYNOPSIS
  19.      idea [ -e | -d ] [ -r ] [ -ecb | -cbcN | -cfbN | -ofbN ]
  20.           ( -k keyString | -K keyHexString )
  21.           [ inputFile [ ouputFile ] ]
  22.  
  23.      idea [ -h | -H ] [ -tan | -abr ]
  24.           [ -k keyString | -K keyHexString ]
  25.           [ inputFile [ [ ouputFile ] hashvalFile ]
  26.  
  27. DESCRIPTION
  28.      Idea reads inputFile and writes  the  en/decrypted  data  to
  29.      outputFile or writes the hash value to hashvalFile.  If file
  30.      name is not given in command line, idea uses standard  input
  31.      or  output.   If  the  input file name is given as '-', idea
  32.      reads from the standard input.
  33.  
  34.      IDEA (International Data Encryption Algorithm)  is  a  block
  35.      cipher developed by Xuejia Lai and Prof. Dr. J. L. Massey at
  36.      the Swiss Federal Institute of Technology.
  37.  
  38. OPTIONS
  39.      -e   Encrypt data. (default)
  40.  
  41.      -d   Decrypt data.
  42.  
  43.      -r   InputFile is a raster-file.
  44.  
  45.      -k   Key is specified with keyString.
  46.  
  47.      -K   Key and initial values are specified with keyHexString.
  48.  
  49.      -h   Compute a 128 bit hash value from the input  data.  The
  50.           hash  value is written to hashvalFile (or standard out-
  51.           put).
  52.  
  53.      -H   Compute a 128 bit hash value from the input  data.  The
  54.           input  is copied to outputFile (or standard output) and
  55.           the hash value is written to hashvalFile  (or  standard
  56.           error).
  57.  
  58.      Notation:
  59.           N           = interleave factor (1 is default)
  60.           z           = 128 bit key
  61.           x[i]        = 64 bit plaintext block
  62.           y[i]        = 64 bit ciphertext block
  63.           x[1]..x[L]  = plaintext  (last  block  is  filled  with
  64.                         zeros)
  65.           x[L+1]      = length of plaintext in bits
  66.           y[1]..y[L+1]= ciphertext
  67.           IDEA(z, .)  = encryption function
  68.           IIDEA(z, .) = decryption function
  69.           x = IIDEA(z, IDEA(z ,x))
  70.  
  71.      Encryption / Decrypion Modes:
  72.  
  73.      -ecb electronic code book mode
  74.           y[i] = IDEA(z, x[i])
  75.           x[i] = IIDEA(z, y[i])
  76.  
  77.      -cbc cipher block chaining mode (cbc1 is default)
  78.           y[i] = IDEA(z, x[i] ^ y[i-N])
  79.           x[i] = IIDEA(z, y[i]) ^ y[i-N]
  80.  
  81.      -cfb ciphertext feedback mode
  82.           y[i] = x[i] ^ IDEA(z, y[i-N])
  83.           x[i] = y[i] ^ IDEA(z, y[i-N])
  84.  
  85.      -ofb output feedback mode
  86.           h[i] = IDEA(z, h[i-N])
  87.           y[i] = x[i] ^ h[i]
  88.           x[i] = y[i] ^ h[i]
  89.  
  90.      Hash Functions:
  91.           If no key is given, idea uses the all zero key.
  92.           hash value = h[L+1] * 2**64 + g[L+1]
  93.           h[0] = z / 2**64
  94.           g[0] = z % 2**64
  95.  
  96.      -tan tandem DM-scheme (default)
  97.           w = IDEA(g[i-1] * 2**64 + x[i], h[i-1])
  98.           h[i] = h[i-1] ^ w
  99.           g[i] = g[i-1] ^ IDEA(x[i] * 2**64 + w, g[i-1])
  100.  
  101.      -abr abreast DM-scheme
  102.           h[i] = h[i-1] ^ IDEA(g[i-1] * 2**64 + x[i], h[i-1])
  103.           g[i] = g[i-1] ^ IDEA(x[i] * 2**64 + h[i-1], ~ g[i-1])
  104.  
  105.      Key Formats:
  106.           keyHexString = { '0'..'9' | 'a'..'f' | 'A'..'F' | ':' }
  107.           keyHexString = z:y[1-N]:y[2-N]:y[3-N]..
  108.           keyString = { '!'..'~' } = z
  109.  
  110. EXAMPLES
  111.      To encrypt and decrypt a file in cipher block chaining  mode
  112.      with an interleave factor of 8:
  113.  
  114.           idea -e -cbc8 -K 12345:67:89::ab:cDEf data data.cr
  115.           idea -d -cbc8 -K 12345:67:89::ab:cDef data.cr data.ori
  116.           data and data.ori are identical
  117.  
  118.      To compute the hash value with tandem DM-scheme:
  119.  
  120.           idea -h data
  121.  
  122.      To compute the hash value and encrypt the data in one step:
  123.  
  124.           idea -Hk "k e y" data | idea -K 123:9a::eF - data.cr
  125.  
  126. PATENT
  127.      IDEA is registered as the international patent  WO  91/18459
  128.      "Device for Converting a Digital Block and the Use thereof".
  129.      For commercial use of IDEA, one should contact
  130.  
  131.      ASCOM TECH AG
  132.      Freiburgstrasse 370
  133.      CH-3018 Bern, Switzerland
  134.  
  135. AUTHOR
  136.      Richard De Moliner (demoliner@isi.ethz.ch)
  137.      Signal and Information Processing Laboratory
  138.      Swiss Federal Institute of Technology
  139.      CH-8092 Zurich, Switzerland
  140.  
  141. BUGS
  142.      This program is at most as strong as  IDEA  itself.  So,  we
  143.      urge  the user to use this program only after he has assured
  144.      himself that IDEA is strong  enough  AND  he  has  read  the
  145.      source  code  of  this  program and its libraries AND he has
  146.      compiled the program himself with a troyan-free compiler. WE
  147.      DO  NOT  GUARANTEE  THAT THIS PROGRAM IS A DECENT ENCRYPTION
  148.      PROGRAM.
  149.  
  150. \******************************************************************************/
  151.  
  152. #ifdef rasterAndTime
  153. #include <sys/times.h>
  154. #include <pixrect/pixrect_hs.h>
  155. #endif
  156.  
  157. #include <stdio.h>
  158. #include <string.h>
  159. #include <crypt.h>
  160.  
  161. #define TRUE                 1 /* boolean constant for true                   */
  162. #define FALSE                0 /* boolean constant for false                  */
  163. #define nofTestData     163840 /* number of blocks encrypted in time test     */
  164.  
  165. #define nomode               0 /* no mode is specified                        */
  166. #define ecb                  1 /* electronic code book mode                   */
  167. #define cbc                  2 /* cipher block chaining mode                  */
  168. #define cfb                  3 /* ciphertext feedback mode                    */
  169. #define ofb                  4 /* output feedback mode                        */
  170. #define tan                  5 /* tandem DM-scheme for hashing                */
  171. #define abr                  6 /* abreast DM-scheme for hashing               */
  172. #define error               -1 /* error constant                              */
  173. #define eol                 -2 /* end of line                                 */
  174. #define colon               -3 /* character ':'                               */
  175. #define maxInterleave     1024 /* maximal interleave factor + 1               */
  176. #define nofChar ('~' - '!' + 1) /* number of different printable characters   */
  177. #define maxBufLen  (dataSize * 1024) /* size of input and output buffer       */
  178.  
  179. UserKeyT(userKey);             /* user selected 128 bit key                   */
  180. KeyT(key);                     /* expanded key with 832 bits                  */
  181. DataT(state[maxInterleave]);   /* state informations for interleaving modes   */
  182. DataT(hashLow);                /* lower 64 bits of hash value                 */
  183. DataT(hashHigh);               /* higher 64 bits of hash value                */
  184.  
  185. u_int32 inputLen    = 0;       /* current number of bytes read from 'inFile'  */
  186. int interleave      = 0;       /* current interleave factor                   */
  187. int time            = 0;       /* time for interleaving modes                 */
  188. int time_N          = 0;       /* time-interleave for interleaving modes      */
  189. int mode            = nomode;  /* current mode                                */
  190.  
  191. int optEncrypt      = FALSE;   /* encrypt option 'e'                          */
  192. int optDecrypt      = FALSE;   /* decrypt option 'd'                          */
  193. int optHash         = FALSE;   /* hash option 'h'                             */
  194. int optCopyHash     = FALSE;   /* copy and hash option 'H'                    */
  195. int optKeyHexString = FALSE;   /* key as hex-string option 'K'                */
  196. int optKeyString    = FALSE;   /* key as string option 'k'                    */
  197. int optRas          = FALSE;   /* raster file option 'r'                      */
  198. int optTime         = FALSE;   /* measure time option 'T'                     */
  199.  
  200. int inBufLen        = maxBufLen; /* current length of data in 'inBuf'         */
  201. int inBufPos        = maxBufLen; /* current read position of 'inBuf'          */
  202. int outBufLen       = 0;       /* current write position of 'outBuf'          */
  203. u_int8 inBuf[maxBufLen];       /* buffer for file read                        */
  204. u_int8 outBuf[maxBufLen];      /* buffer for file write                       */
  205.  
  206. FILE *inFile;                  /* file with input data (plain or ciphertext)  */
  207. FILE *outFile;                 /* file for output data (plain or ciphertext)  */
  208. FILE *hashFile;                /* 128 bit hash value is written to this file  */
  209.  
  210. #ifdef rasterAndTime
  211. int pictureSize;               /* stuff related to raster files               */
  212. Pixrect *picPtr;
  213. colormap_t colormap;
  214. u_int8 *picture;
  215. #endif
  216.  
  217. /******************************************************************************/
  218. /* initialize global variables                                                */
  219.  
  220. void Init()
  221.  
  222. { int i, pos;
  223.  
  224.   for (i = 0; i < userKeyLen; i++) userKey[i] = 0;
  225.   for (pos = 0; pos < maxInterleave; pos++) {
  226.     for (i = 0; i < dataLen; i++) {
  227.       state[pos][i] = 0;
  228.     }
  229.   }
  230. } /* Init */
  231.  
  232. /******************************************************************************/
  233. /*                          E R R O R - H A N D L I N G                       */
  234. /******************************************************************************/
  235. /* write usage error message and terminate program                            */
  236.  
  237. void UsageError(num)
  238.  
  239. int num;
  240. {
  241. #ifdef rasterAndTime
  242. fprintf(stderr, "(%d)\n\
  243. Usage:   idea [ -e | -d ] [ -r ] [ -ecb | -cbcN | -cfbN | -ofbN ]\n\
  244.               ( -k keyString | -K keyHexString )                 \n\
  245.               [ inputFile [ outputFile ] ]                       \n\
  246.          idea [ -h | -H ] [ -tan | -abr ]                        \n\
  247.               [ -k keyString | -K keyHexString ]                 \n\
  248.               [ inputFile [ [ outputFile ] hashvalFile ] ]       \n\
  249.          idea -T                                                 \n\
  250. \nExample: idea -Hk \"k e y\" infile | idea -cbc8 -K 123:9a::eF - outfile\n\
  251. \n", num);
  252. #else
  253. fprintf(stderr, "(%d)\n\
  254. Usage:   idea [ -e | -d ] [ -ecb | -cbcN | -cfbN | -ofbN ]       \n\
  255.               ( -k keyString | -K keyHexString )                 \n\
  256.               [ inputFile [ outputFile ] ]                       \n\
  257.          idea [ -h | -H ] [ -tan | -abr ]                        \n\
  258.               [ -k keyString | -K keyHexString ]                 \n\
  259.               [ inputFile [ [ outputFile ] hashvalFile ] ]       \n\
  260. \nExample: idea -Hk \"k e y\" infile | idea -cbc8 -K 123:9a::eF - outfile\n\
  261. \n", num);
  262. #endif
  263.   exit(-1);
  264. } /* UsageError */
  265.  
  266. /******************************************************************************/
  267. /* write error message and terminate program                                  */
  268.  
  269. void Error(num, str)
  270.  
  271. int num;
  272. char *str;
  273. {  fprintf(stderr, "error %d in idea: %s\n", num, str); exit(-1); } /* Error */
  274.  
  275. /******************************************************************************/
  276. /* write system error message and terminate program                           */
  277.  
  278. void PError(str)
  279.  
  280. char *str;
  281. { perror(str); exit(-1); } /* PError */
  282.  
  283. /******************************************************************************/
  284. /*                          D E C R Y P T I O N  /  E N C R Y P T I O N       */
  285. /******************************************************************************/
  286. /* read one data-block from 'inFile'                                          */
  287.  
  288. int GetData(data)
  289.  
  290. DataT(data);
  291. { register int i, len;
  292.   register u_int16 h;
  293.   register u_int8 *inPtr;
  294.  
  295.   if (inBufPos >= inBufLen) {
  296.     if (inBufLen != maxBufLen) return 0;
  297.     inBufLen = fread(inBuf, 1, maxBufLen, inFile);
  298.     inBufPos = 0;
  299.     if (inBufLen == 0) return 0;
  300.     if (inBufLen % dataSize != 0)
  301.       for (i = inBufLen; i % dataSize != 0; i++) inBuf[i] = 0;
  302.   }
  303.   inPtr = &inBuf[inBufPos];
  304.   for (i = 0; i < dataLen; i++) {
  305.     h = ((u_int16)(*inPtr++) & 0xFF) << 8;
  306.     data[i] = h | ((u_int16)(*inPtr++) & 0xFF);
  307.   }
  308.   inBufPos += dataSize;
  309.   if (inBufPos <= inBufLen) len = dataSize;
  310.   else len = inBufLen + dataSize - inBufPos;
  311.   inputLen += len;
  312.   return len;
  313. } /* GetData */
  314.  
  315. /******************************************************************************/
  316. /* write one data-block to 'outFile'                                          */
  317.  
  318. void PutData(data, len)
  319.  
  320. DataT(data);
  321. int len;
  322. { register int i;
  323.   register u_int16 h;
  324.   register u_int8 *outPtr;
  325.  
  326.   outPtr = &outBuf[outBufLen];
  327.   for (i = 0; i < dataLen; i++) {
  328.     h = data[i];
  329.     *(outPtr++) = (h >> 8) & 0xFF;
  330.     *(outPtr++) = h & 0xFF;
  331.   }
  332.   outBufLen += len;
  333.   if (outBufLen >= maxBufLen) {
  334.     fwrite(outBuf, 1, maxBufLen, outFile);
  335.     outBufLen = 0;
  336.   }
  337. } /* PutData */
  338.  
  339. /******************************************************************************/
  340. /* write last block to 'outFile' and close 'outFile'                          */
  341.  
  342. void CloseOutput()
  343.  
  344. { if (outBufLen > 0) {
  345.     fwrite(outBuf, 1, outBufLen, outFile);
  346.     outBufLen = 0;
  347.   }
  348.   close(outFile);
  349. } /* CloseOutput */
  350.  
  351. /******************************************************************************/
  352. /* increment time and time_N                                                  */
  353.  
  354. void IncTime()
  355. { time = (time + 1) % maxInterleave;
  356.   time_N = (time_N + 1) % maxInterleave;
  357. } /* IncTime */
  358.  
  359. /******************************************************************************/
  360. /* encrypt one data-block                                                     */
  361.  
  362. void EncryptData(data)
  363.  
  364. DataT(data);
  365. { int i;
  366.  
  367.   switch (mode) {
  368.     case ecb:
  369.       Idea(data, data, key);
  370.       break;
  371.     case cbc:
  372.       for (i = dataLen - 1; i >= 0; i--) data[i] ^= state[time_N][i];
  373.       Idea(data, data, key);
  374.       for (i = dataLen - 1; i >= 0; i--) state[time][i] = data[i];
  375.       IncTime();
  376.       break;
  377.     case cfb:
  378.       Idea(state[time_N], state[time], key);
  379.       for (i = dataLen - 1; i >= 0; i--) data[i] = state[time][i] ^= data[i];
  380.       IncTime();
  381.       break;
  382.     case ofb:
  383.       Idea(state[time_N], state[time], key);
  384.       for (i = dataLen - 1; i >= 0; i--) data[i] ^= state[time][i];
  385.       IncTime();
  386.       break;
  387.     default: break;
  388.   }
  389. } /* EncryptData */
  390.  
  391. /******************************************************************************/
  392. /* decrypt one data-block                                                     */
  393.  
  394. void DecryptData(data)
  395.  
  396. DataT(data);
  397. { int i;
  398.  
  399.   switch (mode) {
  400.     case ecb:
  401.       Idea(data, data, key);
  402.       break;
  403.     case cbc:
  404.       for (i = dataLen - 1; i >= 0; i--) state[time][i] = data[i];
  405.       Idea(data, data, key);
  406.       for (i = dataLen - 1; i >= 0; i--) data[i] ^= state[time_N][i];
  407.       IncTime();
  408.       break;
  409.     case cfb:
  410.       for (i = dataLen - 1; i >= 0; i--) state[time][i] = data[i];
  411.       Idea(state[time_N], data, key);
  412.       for (i = dataLen - 1; i >= 0; i--) data[i] ^= state[time][i];
  413.       IncTime();
  414.       break;
  415.     case ofb:
  416.       Idea(state[time_N], state[time], key);
  417.       for (i = dataLen - 1; i >= 0; i--) data[i] ^= state[time][i];
  418.       IncTime();
  419.       break;
  420.     default: break;
  421.   }
  422. } /* DecryptData */
  423.  
  424. /******************************************************************************/
  425. /* hash one data-block                                                        */
  426.  
  427. void HashData(data)
  428.  
  429. DataT(data);
  430. { int i;
  431.   UserKeyT(userKey);
  432.   KeyT(key);
  433.   DataT(w);
  434.  
  435.   for (i = dataLen - 1; i >= 0; i--) { 
  436.     userKey[i] = hashLow[i];
  437.     userKey[i + dataLen] = data[i]; 
  438.   }
  439.   ExpandUserKey(userKey, key);
  440.   Idea(hashHigh, w, key);
  441.   if (mode == abr) {
  442.     for (i = dataLen - 1; i >= 0; i--) { 
  443.       userKey[i] = data[i];
  444.       userKey[i + dataLen] = hashHigh[i]; 
  445.       hashHigh[i] ^= w[i];
  446.       w[i] = ~ hashLow[i];
  447.     }
  448.   }
  449.   else { /* mode == tan */
  450.     for (i = dataLen - 1; i >= 0; i--) {
  451.       hashHigh[i] ^= w[i];
  452.       userKey[i] = data[i];
  453.       userKey[i + dataLen] = w[i];
  454.       w[i] = hashLow[i];
  455.     }
  456.   }
  457.   ExpandUserKey(userKey, key);
  458.   Idea(w, w, key);
  459.   for (i = dataLen - 1; i >= 0; i--) hashLow[i] ^= w[i];
  460. } /* HashData */
  461.  
  462. /******************************************************************************/
  463. /* write value of a 16-bit unsigned integer in hex format to 'hashFile'       */
  464.  
  465. void WriteHex(val)
  466.  
  467. u_int16 val;
  468. { char str[8];
  469.   int i;
  470.  
  471.   sprintf(str, "%4X", val);
  472.   for (i = 0; i < 4; i++) if (str[i] == ' ') str[i] = '0';
  473.   fprintf(hashFile, "%s", str);
  474. } /* WriteHex */
  475.  
  476. /******************************************************************************/
  477. /* write the hash value to 'hashFile'                                         */
  478.  
  479. void WriteHashValue()
  480.  
  481. { int i;
  482.  
  483.   for (i = 0; i < dataLen; i++) WriteHex(hashHigh[i]);
  484.   for (i = 0; i < dataLen; i++) WriteHex(hashLow[i]);
  485. } /* WriteHashValue */
  486.  
  487. /******************************************************************************/
  488. /* store integer 'value' in 'data'                                            */
  489.  
  490. void PlainLenToData(value, data)
  491.  
  492. u_int32 value;
  493. DataT(data);
  494. { data[3] = (u_int16)((value << 3) & 0xFFFF);
  495.   data[2] = (u_int16)((value >> 13) & 0xFFFF);
  496.   data[1] = (u_int16)((value >> 29) & 0x0007);
  497.   data[0] = 0;
  498. } /* PlainLenToData */
  499.  
  500. /******************************************************************************/
  501. /* extract integer 'value' from 'data'                                        */
  502.  
  503. void DataToPlainLen(data, value)
  504.  
  505. DataT(data);
  506. u_int32 *value;
  507. { if ((data[0] != 0) || (data[1] > 7) || ((data[3] & 7) != 0))
  508.     Error(1, "input is not a valid cryptogram");
  509.   *value = ((u_int32)(data[3]) >> 3) & 0x1FFF |
  510.            ((u_int32)(data[2]) << 13) |
  511.            ((u_int32)(data[1]) << 29);
  512. } /* DataToPlainLen */
  513.  
  514. /******************************************************************************/
  515. /* encrypt / decrypt complete data-stream or compute hash value of data-stream*/
  516.  
  517. void CryptData()
  518.  
  519. { int t, i;
  520.   u_int32 len;
  521.   DataT(dat[4]);
  522.   DataT(data);
  523.  
  524.   if (optRas) {
  525. #ifdef rasterAndTime
  526.     if (optEncrypt)
  527.       for (i = 0; i <= (pictureSize - dataSize); i += dataSize)
  528.         EncryptData((u_int16 *)&picture[i]);
  529.     else
  530.       for (i = 0; i <= (pictureSize - dataSize); i += dataSize)
  531.         DecryptData((u_int16 *)&picture[i]);
  532. #endif
  533.   }
  534.   else if (optEncrypt) { /* encrypt data */
  535.     while ((len = GetData(data)) == dataSize) {
  536.       EncryptData(data); 
  537.       PutData(data, dataSize); 
  538.     }
  539.     if (len > 0) { EncryptData(data); PutData(data, dataSize); }
  540.     PlainLenToData(inputLen, data);
  541.     EncryptData(data);
  542.     PutData(data, dataSize);
  543.     CloseOutput();
  544.   }
  545.   else if (optDecrypt) { /* decrypt data */
  546.     if ((len = GetData(dat[0])) != dataSize) {
  547.       if (len != 0) Error(2, "input is not a valid cryptogram");
  548.       else Error(3, "there are no data to decrypt");
  549.     }
  550.     DecryptData(dat[0]);
  551.     if ((len = GetData(dat[1])) != dataSize) {
  552.       if (len != 0) Error(4, "input is not a valid cryptogram");
  553.       DataToPlainLen(dat[0], &len);
  554.       if (len != 0) Error(5, "input is not a valid cryptogram");
  555.     }
  556.     else {
  557.       DecryptData(dat[1]);
  558.       t = 2;
  559.       while ((len = GetData(dat[t])) == dataSize) {
  560.         DecryptData(dat[t]);
  561.         PutData(dat[(t + 2) & 3], dataSize);
  562.         t = (t + 1) & 3;
  563.       }
  564.       if (len != 0) Error(6, "input is not a valid cryptogram");
  565.       DataToPlainLen(dat[(t + 3) & 3], &len);
  566.       len += 2 * dataSize;
  567.       if ((inputLen < len) && (len <= inputLen + dataSize)) {
  568.         len -= inputLen;
  569.         PutData(dat[(t + 2) & 3], len);
  570.       }
  571.       else Error(7, "input is not a valid cryptogram");
  572.     }
  573.     CloseOutput();
  574.   }
  575.   else { /* compute hash value */
  576.     for (i = dataLen - 1; i >= 0; i--) {
  577.       hashHigh[i] = userKey[i];
  578.       hashLow[i] = userKey[i + dataLen];
  579.     }
  580.     if (optCopyHash) { 
  581.       while ((len = GetData(data)) == dataSize) {
  582.         HashData(data); 
  583.         PutData(data, dataSize); 
  584.       }
  585.       if (len > 0) { HashData(data); PutData(data, len); }
  586.       PlainLenToData(inputLen, data);
  587.       HashData(data);
  588.       CloseOutput();
  589.     }
  590.     else { /* optHash */
  591.       while ((len = GetData(data)) == dataSize) HashData(data); 
  592.       if (len > 0) HashData(data);
  593.       PlainLenToData(inputLen, data);
  594.       HashData(data);
  595.     }
  596.     WriteHashValue();
  597.   }
  598. } /* CryptData */
  599.  
  600. /******************************************************************************/
  601. /* measure the time to encrypt 'nofTestData' data-blocks                      */
  602.  
  603. void TimeTest()
  604.  
  605. #ifdef rasterAndTime
  606.   struct tms startTime, endTime;
  607.   DataT(data);
  608.   int i;
  609.   float size, time;
  610.  
  611.   for (i = 0; i < dataLen; i++) data[i] = 0;
  612.   if (times(&startTime) != 0) PError("(8) times");
  613.   for (i = 0; i < nofTestData; i++) Idea(data, data, key);
  614.   if (times(&endTime) != 0) PError("(9) times");
  615.   size = ((float)nofTestData * 8.0 * (float)(dataSize)) / 1048576.0;
  616.   time = (endTime.tms_utime - startTime.tms_utime) / 60.0;
  617.   fprintf(stderr, "user time needed to encrypt %4.1f MBit of data was %4.1f\
  618.  seconds (%6.3f MBit/sec)\n", size, time, size/time);
  619. #endif
  620. } /* TimeTest */
  621.  
  622. /******************************************************************************/
  623. /*                          I N I T I A L I Z A T I O N                       */
  624. /******************************************************************************/
  625. /* set option to TRUE                                                         */
  626.  
  627. void SetOption(option)
  628.  
  629. int *option;
  630. { if (*option) UsageError(10);
  631.   *option = TRUE;
  632. } /* SetOption */
  633.  
  634. /******************************************************************************/
  635. /* set encryption / decryption mode                                           */
  636.  
  637. void SetMode(newMode, str)
  638.  
  639. int newMode;
  640. char **str;
  641. { if (mode != nomode) UsageError(11);
  642.   mode = newMode;
  643.   (*str)++; (*str)++;
  644.   if ((newMode == cbc) || (newMode == cfb) || (newMode == ofb)) {
  645.     if (('0' <= **str) && (**str <= '9')) {
  646.       interleave = 0;
  647.       do {
  648.         interleave = 10 * interleave + (**str - '0');
  649.         if (interleave >= maxInterleave)
  650.           Error(12, "interleave factor is too large");
  651.         (*str)++;
  652.       } while (('0' <= **str) && (**str <= '9'));
  653.       if (interleave == 0) Error(13, "interleave factor is zero");
  654.     }
  655.     else interleave = 1;
  656.   }
  657. } /* SetMode */
  658.  
  659. /******************************************************************************/
  660. /* read options from string 'str'                                             */
  661.  
  662. void ReadOptions(str, readKeyString, readKeyHexString)
  663.  
  664. char *str;
  665. int *readKeyString, *readKeyHexString;
  666. { char ch;
  667.  
  668.   str++;
  669.   *readKeyString = *readKeyHexString = FALSE;
  670.   while((ch = *(str++)) != 0) {
  671.     switch (ch) {
  672.       case 'a':
  673.         if ((str[0] == 'b') && (str[1] == 'r')) SetMode(abr, &str);
  674.         else UsageError(14);
  675.         break;
  676.       case 'c':
  677.         if ((str[0] == 'b') && (str[1] == 'c')) SetMode(cbc, &str);
  678.         else if ((str[0] == 'f') && (str[1] == 'b')) SetMode(cfb, &str);
  679.         else UsageError(15);
  680.         break;
  681.       case 'd': SetOption(&optDecrypt); break;
  682.       case 'e': 
  683.         if ((str[0] == 'c') && (str[1] == 'b')) SetMode(ecb, &str);
  684.         else SetOption(&optEncrypt);
  685.         break;
  686.       case 'h': SetOption(&optHash); break;
  687.       case 'H': SetOption(&optCopyHash); break;
  688.       case 'o':
  689.         if ((str[0] == 'f') && (str[1] == 'b')) SetMode(ofb, &str);
  690.         else UsageError(16);
  691.         break;
  692.       case 'k': SetOption(&optKeyString); *readKeyString = TRUE; break;
  693.       case 'K': SetOption(&optKeyHexString); *readKeyHexString = TRUE; break;
  694.       case 't':
  695.         if ((str[0] == 'a') && (str[1] == 'n')) SetMode(tan, &str);
  696.         else UsageError(17);
  697.         break;
  698. #ifdef rasterAndTime
  699.       case 'r': SetOption(&optRas); break;
  700.       case 'T': SetOption(&optTime); break;
  701. #endif
  702.       default: UsageError(18); break;
  703.     }
  704.   }
  705.   if (*readKeyString && *readKeyHexString) UsageError(19);
  706. } /* ReadOptions */
  707.  
  708. /******************************************************************************/
  709. /* check if options are unique and set default options                        */
  710.  
  711. void AdjustOptions()
  712.  
  713. { if (optTime && (optDecrypt || optEncrypt || optHash || optCopyHash ||
  714.       optKeyString || optKeyHexString || optRas)) UsageError(20);
  715.   if (optDecrypt && optEncrypt) UsageError(21);
  716.   if (optHash && optCopyHash) UsageError(22);
  717.   if (optKeyString && optKeyHexString) UsageError(23);
  718.   if (optDecrypt || optEncrypt) {
  719.     if (optHash || optCopyHash) UsageError(24);
  720.     if ((! optKeyString) && (! optKeyHexString)) UsageError(25);
  721.     if (mode == nomode) { mode = cbc; interleave = 1; }
  722.     else if ((mode == tan) || (mode == abr)) UsageError(26);
  723.   }
  724.   else {
  725.     if (optHash || optCopyHash) {
  726.       if (mode == nomode) mode = tan;
  727.       else if ((mode != tan) && (mode != abr)) UsageError(27);
  728.     }
  729.     else {
  730.       if (mode == nomode) { mode = cbc; interleave = 1; }
  731.       if ((mode == tan) || (mode == abr)) SetOption(&optHash);
  732.       else SetOption(&optEncrypt);
  733.     }
  734.   }
  735.   if (optRas && (optHash || optCopyHash)) UsageError(28);
  736.   time = interleave;
  737.   time_N = 0;
  738. } /* AdjustOptions */
  739.  
  740. /******************************************************************************/
  741. /* convert a hex-digit into an integer                                        */
  742.  
  743. int HexToInt(ch)
  744.  
  745. char ch;
  746. {
  747.   if (('0' <= ch) && (ch <= '9')) return ch - '0';
  748.   else if (('a' <= ch)  && (ch <= 'f')) return 10 + (ch - 'a');
  749.   else if (('A' <= ch) && (ch <= 'F')) return 10 + (ch - 'A');
  750.   else if (ch == ':') return colon;
  751.   else if (ch == 0) return eol;
  752.   else return error;
  753. } /* HexToInt */
  754.  
  755. /******************************************************************************/
  756. /* convert a character into an integer                                        */
  757.  
  758. int32 CharToInt(ch)
  759.  
  760. char ch;
  761. {
  762.   if (('!' <= ch) && (ch <= '~')) return ch - '!';
  763.   else if (ch == 0) return eol;
  764.   else return error;
  765. } /* CharToInt */
  766.  
  767. /******************************************************************************/
  768. /* initializes key and initial values                                                */
  769.  
  770. void ReadKeyHexString(str)
  771.  
  772. char *str;
  773. { int i, pos;
  774.   int32 h, val;
  775.  
  776.   while ((val = HexToInt(*(str++))) >= 0) {
  777.     for (i = userKeyLen - 1; i >= 0; i--) {
  778.       h = ((int32)(userKey[i]) >> 12) & 0xF;
  779.       userKey[i] = ((int32)(userKey[i]) << 4) | val;
  780.       val = h;
  781.     }
  782.     if (val != 0) Error(29, "key value is too large");
  783.   }
  784.   pos = 0;
  785.   while ((val == colon) && (pos < maxInterleave)) {
  786.     val = HexToInt(*(str++));
  787.     while (val >= 0) {
  788.       for (i = dataLen - 1; i >= 0; i--) {
  789.         h = ((int32)(state[pos][i]) >> 12) & 0xF;
  790.         state[pos][i] = ((int32)(state[pos][i]) << 4) | val;
  791.         val = h;
  792.       }
  793.       if (val != 0) Error(30, "initial value is too large");
  794.       val = HexToInt(*(str++));
  795.     }
  796.     pos++;
  797.   }
  798.   if (val == colon) Error(31, "too many initial values specified");
  799.   if (val != eol) Error(32, "wrong character in initialization string");
  800. } /* ReadKeyHexString */
  801.  
  802. /******************************************************************************/
  803. /* initialize key and initial values                                          */
  804.  
  805. void ReadKeyString(str)
  806.  
  807. char *str;
  808. { int i;
  809.   int32 h, val;
  810.  
  811.   while ((val = CharToInt(*(str++))) >= 0) {
  812.     for (i = userKeyLen - 1; i >= 0; i--) {
  813.       h = (int32)(userKey[i]) * nofChar + val;
  814.       userKey[i] = h & 0xFFFF;
  815.       val = h >> 16;
  816.     }
  817.   }
  818. } /* ReadKeyString */
  819.  
  820. /******************************************************************************/
  821. /* show value of a 16-bit unsigned integer in decimal and hex format          */
  822.  
  823. void ShowInt16(val)
  824.  
  825. u_int16 val;
  826. { fprintf(stderr, "%7u<%4x>", val, val);
  827. } /* ShowInt16 */
  828.  
  829. /******************************************************************************/
  830. /* show option name if option is set                                          */
  831.  
  832. void ShowOption(option, name)
  833.  
  834. int option;
  835. char *name;
  836. { if (option) fprintf(stderr, ", %s", name);
  837. } /* ShowOption */
  838.  
  839.  
  840. /******************************************************************************/
  841. /* show current state informations                                            */
  842.  
  843. void ShowState()
  844.  
  845. { int i, j;
  846.  
  847.   fprintf(stderr, "Mode = {");
  848.   switch (mode) {
  849.     case ecb: fprintf(stderr, "ecb"); break;
  850.     case cbc: fprintf(stderr, "cbc"); break;
  851.     case cfb: fprintf(stderr, "cfb"); break;
  852.     case ofb: fprintf(stderr, "ofb"); break;
  853.     case tan: fprintf(stderr, "tan"); break;
  854.     case abr: fprintf(stderr, "abr"); break;
  855.     case nomode: fprintf(stderr, "nomode"); break;
  856.     default: fprintf(stderr, "!!!wrong mode!!!"); break;
  857.   }
  858.   if (interleave > 0) fprintf(stderr, "%d", interleave);
  859.   ShowOption(optEncrypt, "encrypt");
  860.   ShowOption(optDecrypt, "decrypt");
  861.   ShowOption(optHash, "hash");
  862.   ShowOption(optCopyHash, "copy and hash");
  863.   ShowOption(optKeyString, "key string");
  864.   ShowOption(optKeyHexString, "key hex string");
  865.   ShowOption(optRas, "raster file");
  866.   ShowOption(optTime, "time test");
  867.   fprintf(stderr, "}\n\nKey:\n");
  868.   for (i = 0; i < keyLen; i++) {
  869.     ShowInt16(key[i]);
  870.     if ((i % 6) == 5) fprintf(stderr, "\n");
  871.   }
  872.   fprintf(stderr, "\n\nInitial values:");
  873.   for (i = 0; i < interleave; i++) {
  874.     fprintf(stderr, "\n  x[N -%2d] =", i + 1);
  875.     for (j = 0; j < dataLen; j++) ShowInt16(state[i][j]);
  876.   }
  877.   fprintf(stderr, "\n");
  878. } /* ShowState */
  879.  
  880. /******************************************************************************/
  881. /* read picture from 'inFile' to memory                                       */
  882.  
  883. void ReadRasFile()
  884.  
  885. {
  886. #ifdef rasterAndTime
  887.   if ((picPtr = pr_load(inFile, &colormap)) == NULL)
  888.     PError("(33) input is not a rasterfile");
  889.   if (picPtr->pr_depth != 8) Error(34, "depth of rasterfile should bee 8");
  890.   picture = (u_int8 *)mpr_d(picPtr)->md_image;
  891.   pictureSize = picPtr->pr_height * picPtr->pr_width;
  892. #endif
  893. } /* ReadRasFile */
  894.  
  895. /******************************************************************************/
  896. /* write picture from memory to 'outFile'                                     */
  897.  
  898. void WriteRasFile()
  899.  
  900. {
  901. #ifdef rasterAndTime
  902.   if (pr_dump(picPtr, outFile, &colormap, RT_STANDARD, FALSE) != NULL)
  903.     PError("(34) writing rasterfile");
  904. #endif
  905. } /* WriteRasFile */
  906.  
  907. /******************************************************************************/
  908. /*                          M A I N - P R O C E D U R E                       */
  909. /******************************************************************************/
  910. main(argc, argv)
  911.  
  912. int argc;
  913. char *argv[];
  914. { int readKeyString, readKeyHexString;
  915.  
  916.   Init();
  917.   argv++; argc--;
  918.   while ((argc > 0) && (*(argv[0]) == '-') && (*(argv[0]+1) != '\0')) {
  919.     ReadOptions(*argv++, &readKeyString, &readKeyHexString); argc--;
  920.     if (readKeyString || readKeyHexString) {
  921.       if (argc <= 0)  Error(36, "missing key on command line");
  922.       else if (readKeyString) { ReadKeyString(*(argv++)); argc--; }
  923.       else { ReadKeyHexString(*(argv++)); argc--; }
  924.     }
  925.   }
  926.   AdjustOptions();
  927.   if ((optTime && (argc > 0)) || (optCopyHash && (argc > 3)) || 
  928.       (! optCopyHash && (argc > 2))) Error(37, "too many parameters");
  929.   if (optTime) TimeTest();
  930.   else {
  931.     if ((argc > 1) && (strcmp(argv[0], argv[1]) == 0))
  932.       Error(38, "source and destination are identical");
  933.     if ((argc > 2) && (strcmp(argv[0], argv[2]) == 0))
  934.       Error(39, "source and destination are identical");
  935.     if ((argc > 2) && (strcmp(argv[1], argv[2]) == 0))
  936.       Error(40, "destinations are identical");
  937.     inFile = stdin;
  938.     outFile = hashFile = stdout;
  939.     if (argc > 0) {
  940.       if (strcmp(*argv, "-") == 0) { argv++; argc--; }
  941.       else {
  942.         inFile = fopen(*argv++, "r"); argc--;
  943.         if (inFile == 0) PError(*--argv);
  944.       }
  945.     }
  946.     if (optCopyHash) {
  947.       if (argc > 1) {
  948.         outFile = fopen(*argv++, "w"); argc--;
  949.         if (outFile == 0) PError(*--argv);
  950.       }
  951.       if (argc > 0) {
  952.         hashFile = fopen(*argv++, "w"); argc--;
  953.         if (hashFile == 0) PError(*--argv);
  954.       }
  955.       else hashFile = stderr;
  956.     }
  957.     else if (optHash) {
  958.       if (argc > 0) {
  959.         hashFile = fopen(*argv++, "w"); argc--;
  960.         if (hashFile == 0) PError(*--argv);
  961.       }
  962.     }
  963.     else {
  964.       if (argc > 0) {
  965.         outFile = fopen(*argv++, "w"); argc--;
  966.         if (outFile == 0) PError(*--argv);
  967.       }
  968.     }
  969.     if (argc > 0) Error(41, "too many parameters");
  970.     ExpandUserKey(userKey, key);
  971.     if (optDecrypt && ((mode == ecb) || (mode == cbc))) InvertIdeaKey(key, key);
  972. /*  ShowState(); */
  973.     if (optRas) ReadRasFile();
  974.     CryptData();
  975.     if (optRas) WriteRasFile();
  976.   }
  977.   exit(0);
  978. }
  979.